home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / hack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  39.6 KB  |  1,669 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)hack.c    3.1    93/06/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. STATIC_DCL int NDECL(moverock);
  8. #ifdef POLYSELF
  9. STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P));
  10. #endif
  11. #ifdef SINKS
  12. STATIC_DCL void NDECL(dosinkfall);
  13. #endif
  14. STATIC_DCL boolean FDECL(bad_rock,(XCHAR_P,XCHAR_P));
  15. STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int));
  16.  
  17. static void FDECL(move_update, (BOOLEAN_P));
  18.  
  19. #define IS_SHOP(x)    (rooms[x].rtype >= SHOPBASE)
  20.  
  21. #ifdef OVL2
  22.  
  23. boolean
  24. revive_nasty(x, y, msg)
  25. int x,y;
  26. const char *msg;
  27. {
  28.     register struct obj *otmp, *otmp2;
  29.     struct monst *mtmp;
  30.     coord cc;
  31.     boolean revived = FALSE;
  32.  
  33.     /* prevent freeobj() of revivable corpses */
  34.     for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
  35.     otmp2 = otmp->nexthere;
  36.     if (otmp->otyp == CORPSE &&
  37.         (is_rider(&mons[otmp->corpsenm]) ||
  38.          otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
  39.         /* move any living monster already at that location */
  40.         if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
  41.         rloc_to(mtmp, cc.x, cc.y);
  42.         if(msg) Norep("%s", msg);
  43.         revive_corpse(otmp, 0, FALSE);
  44.         revived = MON_AT(x,y);
  45.     }
  46.     }
  47.  
  48.     /* this location might not be safe, if not, move revived monster */
  49.     if (revived) {
  50.     mtmp = m_at(x,y);
  51.     if (mtmp && !goodpos(x, y, mtmp, mtmp->data) &&
  52.         enexto(&cc, x, y, mtmp->data)) {
  53.         rloc_to(mtmp, cc.x, cc.y);
  54.     }
  55.     /* else impossible? */
  56.     }
  57.  
  58.     return (revived);
  59. }
  60.  
  61. STATIC_OVL int
  62. moverock()
  63. {
  64.     register xchar rx, ry;
  65.     register struct obj *otmp, *otmp2;
  66.     register struct trap *ttmp;
  67.     register struct monst *mtmp;
  68.  
  69.     while ((otmp = sobj_at(BOULDER, u.ux+u.dx, u.uy+u.dy)) != 0) {
  70.     rx = u.ux+2*u.dx;
  71.     ry = u.uy+2*u.dy;
  72.     nomul(0);
  73.     if (Levitation || Is_airlevel(&u.uz)) {
  74.         if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  75.         You("don't have enough leverage to push %s.", the(xname(otmp)));
  76.         /* Give them a chance to climb over it? */
  77.         return -1;
  78.     }
  79. #ifdef POLYSELF
  80.     if (verysmall(uasmon)) {
  81.         if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  82.         pline("You're too small to push that %s.", xname(otmp));
  83.         goto cannot_push;
  84.     }
  85. #endif
  86.     if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
  87.         (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
  88. #ifdef REINCARNATION
  89.         !Is_rogue_level(&u.uz) &&
  90. #endif
  91.         (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&
  92.         !sobj_at(BOULDER, rx, ry)) {
  93.         ttmp = t_at(rx, ry);
  94.         mtmp = m_at(rx, ry);
  95.  
  96.         if (revive_nasty(rx, ry, "You sense movement on the other side."))
  97.         return (-1);
  98.  
  99.         if (mtmp && (!mtmp->mtrapped ||
  100.              !(ttmp && ((ttmp->ttyp == PIT) ||
  101.                     (ttmp->ttyp == SPIKED_PIT))))) {
  102.         if (canseemon(mtmp))
  103.             pline("There's %s on the other side.", mon_nam(mtmp));
  104.         else {
  105.             if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  106.             You("hear a monster behind %s.", the(xname(otmp)));
  107.         }
  108.         if (flags.verbose)
  109.             pline("Perhaps that's why you cannot move it.");
  110.         goto cannot_push;
  111.         }
  112.  
  113.         if (ttmp)
  114.         switch(ttmp->ttyp) {
  115.         case SPIKED_PIT:
  116.         case PIT:
  117.             freeobj(otmp);
  118.             /* vision kludge to get messages right;
  119.                the pit will temporarily be seen even
  120.                if this is one among multiple boulders */
  121.             if (!Blind) viz_array[ry][rx] |= IN_SIGHT;
  122.             if (!flooreffects(otmp, rx, ry, "fall")) {
  123.             place_object(otmp, rx, ry);
  124.             otmp->nobj = fobj;
  125.             fobj = otmp;
  126.             }
  127.             continue;
  128.         case TRAPDOOR:
  129.             pline("%s falls into and plugs a hole in the %s!",
  130.               The(xname(otmp)), surface(rx, ry));
  131.             deltrap(ttmp);
  132.             delobj(otmp);
  133.             bury_objs(rx, ry);
  134.             if (cansee(rx,ry)) newsym(rx,ry);
  135.             continue;
  136.         case LEVEL_TELEP:
  137.         case TELEP_TRAP:
  138.             You("push %s and suddenly it disappears!",
  139.             the(xname(otmp)));
  140.             rloco(otmp);
  141.             continue;
  142.         }
  143.         if (closed_door(rx, ry))
  144.         goto nopushmsg;
  145.         if (boulder_hits_pool(otmp, rx, ry, TRUE))
  146.         continue;
  147.         /*
  148.          * Re-link at top of fobj chain so that pile order is preserved
  149.          * when level is restored.
  150.          */
  151.         if (otmp != fobj) {
  152.         otmp2 = fobj;
  153.         while (otmp2->nobj && otmp2->nobj != otmp)
  154.             otmp2 = otmp2->nobj;
  155.         if (!otmp2->nobj) {
  156.             impossible("moverock: error in fobj chain");
  157.         } else {
  158.             otmp2->nobj = otmp->nobj;    
  159.             otmp->nobj = fobj;
  160.             fobj = otmp;
  161.         }
  162.         }
  163.  
  164.         {
  165. #ifdef LINT /* static long lastmovetime; */
  166.         long lastmovetime;
  167.         lastmovetime = 0;
  168. #else
  169.         static NEARDATA long lastmovetime;
  170. #endif
  171.         /* note: this var contains garbage initially and
  172.            after a restore */
  173.         if (moves > lastmovetime+2 || moves < lastmovetime)
  174.             pline("With great effort you move %s.", the(xname(otmp)));
  175.         exercise(A_STR, TRUE);
  176.         lastmovetime = moves;
  177.         }
  178.  
  179.         /* Move the boulder *after* the message. */
  180.         move_object(otmp, rx, ry);
  181.         if (Blind) {
  182.         feel_location(rx,ry);
  183.         feel_location(u.ux+u.dx, u.uy+u.dy);
  184.         } else {
  185.         newsym(rx,ry);
  186.         newsym(u.ux+u.dx, u.uy+u.dy);
  187.         }
  188.     } else {
  189.     nopushmsg:
  190.         You("try to move %s, but in vain.", the(xname(otmp)));
  191.         if (Blind) feel_location(u.ux+u.dx, u.uy+u.dy);
  192.     cannot_push:
  193. #ifdef POLYSELF
  194.         if (throws_rocks(uasmon)) {
  195.         if (!flags.pickup)
  196.             pline("However, you easily can push it aside.");
  197.         else
  198.             pline("However, you easily can pick it up.");
  199.         break;
  200.         }
  201. #endif
  202.         if (((!invent || inv_weight() <= -850) &&
  203.          (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
  204.                      && IS_ROCK(levl[u.ux+u.dx][u.uy].typ))))
  205. #ifdef POLYSELF
  206.         || verysmall(uasmon)
  207. #endif
  208.         ) {
  209.         pline("However, you can squeeze yourself into a small opening.");
  210.         break;
  211.         } else
  212.         return (-1);
  213.     }
  214.     }
  215.     return (0);
  216. }
  217.  
  218. #ifdef POLYSELF
  219. /*
  220.  *  still_chewing()
  221.  *  
  222.  *  Chew on a wall, door, or boulder.  Returns TRUE if still eating, FALSE
  223.  *  when done.
  224.  */
  225. STATIC_OVL int
  226. still_chewing(x,y)
  227.     xchar x, y;
  228. {
  229.     struct rm *lev      = &(levl[x][y]);
  230.     struct obj *boulder = sobj_at(BOULDER,x,y);
  231.     register boolean shopedge = *in_rooms(x, y, SHOPBASE);
  232.     register const char *digtxt = (const char*) 0, *dmgtxt = (const char*) 0;
  233.  
  234.     if (dig_pos.x != x || dig_pos.y != y ||
  235.                 !on_level(&dig_level, &u.uz) || dig_down) {
  236.     if (!boulder && (lev->diggable & W_NONDIGGABLE)) {
  237.         You("hurt your teeth on the hard stone.");
  238.         nomul(0);
  239.     } else {
  240.         dig_down = FALSE;
  241.         dig_pos.x = x;
  242.         dig_pos.y = y;
  243.         assign_level(&dig_level, &u.uz);
  244.         dig_effort = IS_ROCK(lev->typ) ? 30 : 60; /* rock takes more time */
  245.         if (boulder)
  246.         You("start chewing on a boulder.");
  247.         else
  248.         You("start chewing a hole in the %s.",
  249.                     IS_ROCK(lev->typ) ? "rock" : "door");
  250.     }
  251.     return 1;
  252.     } else if ((dig_effort += 30) < 100)  {
  253.     if (flags.verbose)
  254.         You("continue chewing on the %s.", boulder ? "boulder" :
  255.                     (IS_ROCK(lev->typ) ? "rock" : "door"));
  256.     return 1;
  257.     }
  258.  
  259.     if (boulder) {
  260.     delobj(boulder);        /* boulder goes bye-bye */
  261.     You("eat the boulder.");    /* yum */
  262.  
  263.     /*
  264.      *  The location could still block because of
  265.      *      1. More than one boulder
  266.      *      2. Boulder stuck in a wall/stone/door.
  267.      *
  268.      *  [perhaps use does_block() below (from vision.c)]
  269.      */
  270.     if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
  271.         block_point(x,y);    /* delobj will unblock the point */
  272.         dig_pos.x = 0;    /* reset dig messages */
  273.         return 1;
  274.     }
  275.     
  276.     } else if (IS_WALL(lev->typ)) {
  277.     if(shopedge) {
  278.         add_damage(x, y, 10L * ACURRSTR);
  279.         dmgtxt = "damage";
  280.     }
  281.     digtxt = "chew a hole in the wall.";
  282.     if (level.flags.is_maze_lev) {
  283.         lev->typ = ROOM;
  284.     } else if (level.flags.is_cavernous_lev) {
  285.         lev->typ = CORR;
  286.     } else {
  287.         lev->typ = DOOR;
  288.         lev->doormask = D_NODOOR;
  289.     }
  290.     } else if (lev->typ == SDOOR) {
  291.     if (lev->doormask & D_TRAPPED) {
  292.         lev->doormask = D_NODOOR;
  293.         b_trapped("secret door", 0);
  294.     } else {
  295.         digtxt = "chew through the secret door.";
  296.         lev->doormask = D_BROKEN;
  297.     }
  298.     lev->typ = DOOR;
  299.  
  300.     } else if (IS_DOOR(lev->typ)) {
  301.     if(shopedge) {
  302.         add_damage(x, y, 400L);
  303.         dmgtxt = "break";
  304.     }
  305.     if (lev->doormask & D_TRAPPED) {
  306.         lev->doormask = D_NODOOR;
  307.         b_trapped("door", 0);
  308.     } else {
  309.         digtxt = "chew through the door.";
  310.         lev->doormask = D_BROKEN;
  311.     }
  312.  
  313.     } else { /* STONE or SCORR */
  314.     digtxt = "chew a passage through the rock.";
  315.     lev->typ = CORR;
  316.     }
  317.  
  318.     unblock_point(x, y);    /* vision */
  319.     newsym(x, y);
  320.     if (digtxt) You(digtxt);    /* after newsym */
  321.     if (dmgtxt)
  322.     pay_for_damage(dmgtxt);
  323.     dig_level.dnum = 0;
  324.     dig_level.dlevel = -1;
  325.     return 0;
  326. }
  327. #endif /* POLYSELF */
  328.  
  329. #endif /* OVL2 */
  330. #ifdef OVLB
  331.  
  332. void
  333. movobj(obj, ox, oy)
  334. register struct obj *obj;
  335. register xchar ox, oy;
  336. {
  337.     remove_object(obj);
  338.     newsym(obj->ox, obj->oy);
  339.     place_object(obj, ox, oy);
  340.     newsym(ox, oy);
  341. }
  342.  
  343. #ifdef SINKS
  344. STATIC_OVL void
  345. dosinkfall()
  346. {
  347.     register struct obj *obj;
  348.  
  349. # ifdef POLYSELF
  350.     if (is_floater(uasmon)) {
  351.         You("wobble unsteadily for a moment.");
  352.     } else {
  353. # endif
  354.         You("crash to the floor!");
  355.         losehp((rn1(10, 20 - (int)ACURR(A_CON))),
  356.             "fell onto a sink", NO_KILLER_PREFIX);
  357.         exercise(A_DEX, FALSE);
  358.         for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
  359.             if(obj->oclass == WEAPON_CLASS) {
  360.             You("fell on %s.",doname(obj));
  361.             losehp(rn2(3),"fell onto a sink", NO_KILLER_PREFIX);
  362.             exercise(A_CON, FALSE);
  363.             }
  364. # ifdef POLYSELF
  365.     }
  366. # endif
  367.  
  368.     HLevitation = (HLevitation & ~TIMEOUT) + 1;
  369.     if(uleft && uleft->otyp == RIN_LEVITATION) {
  370.         obj = uleft;
  371.         Ring_off(obj);
  372.         off_msg(obj);
  373.     }
  374.     if(uright && uright->otyp == RIN_LEVITATION) {
  375.         obj = uright;
  376.         Ring_off(obj);
  377.         off_msg(obj);
  378.     }
  379.     if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
  380.         obj = uarmf;
  381.         (void)Boots_off();
  382.         off_msg(obj);
  383.     }
  384.     HLevitation--;
  385. }
  386. #endif
  387.  
  388. #endif /* OVLB */
  389.  
  390. #ifdef OVLB
  391.  
  392. boolean
  393. may_dig(x,y)
  394. register xchar x,y;
  395. /* intended to be called only on ROCKs */
  396. {
  397. return((boolean)(!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONDIGGABLE))));
  398. }
  399.  
  400. boolean
  401. may_passwall(x,y)
  402. register xchar x,y;
  403. {
  404. return((boolean)(!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONPASSWALL))));
  405. }
  406.  
  407. #endif /* OVLB */
  408. #ifdef OVL1
  409.  
  410. STATIC_OVL boolean
  411. bad_rock(x,y)
  412. register xchar x,y;
  413. {
  414.     return((boolean)(IS_ROCK(levl[x][y].typ)
  415. #ifdef POLYSELF
  416.             && !(passes_walls(uasmon) && may_passwall(x,y))
  417.             && (!tunnels(uasmon) || needspick(uasmon) || !may_dig(x,y))
  418. #endif
  419.     ));
  420. }
  421.  
  422. boolean
  423. invocation_pos(x, y)
  424. xchar x, y;
  425. {
  426.         return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y));
  427. }
  428.  
  429. #endif /* OVL1 */
  430. #ifdef OVL3
  431.  
  432. void
  433. domove()
  434. {
  435.     register struct monst *mtmp;
  436.     register struct rm *tmpr,*ust;
  437.     register xchar x,y;
  438.     struct trap *trap;
  439.     int wtcap;
  440.     boolean on_ice;
  441.     xchar chainx, chainy, ballx, bally;    /* ball&chain new positions */
  442.     int bc_control;                /* control for ball&chain */
  443.  
  444.     u_wipe_engr(rnd(5));
  445.  
  446.     if(((wtcap = near_capacity()) >= OVERLOADED
  447.         || (wtcap > SLT_ENCUMBER && (u.uhp < 10 && u.uhp != u.uhpmax)))
  448.        && !Is_airlevel(&u.uz)) {
  449.         if(wtcap < OVERLOADED) {
  450.         You("don't have enough stamina to move.");
  451.             exercise(A_CON, FALSE);
  452.         } else
  453.         You("collapse under your load.");
  454.         nomul(0);
  455.         return;
  456.     }
  457.     if(u.uswallow) {
  458.         u.dx = u.dy = 0;
  459.         u.ux = x = u.ustuck->mx;
  460.         u.uy = y = u.ustuck->my;
  461.         mtmp = u.ustuck;
  462.     } else {
  463.         if(Is_airlevel(&u.uz) && rn2(4) && !Levitation
  464. #ifdef POLYSELF
  465.            && !is_flyer(uasmon)
  466. #endif
  467.            ) {
  468.             switch(rn2(3)) {
  469.             case 0:
  470.             You("tumble in place.");
  471.             exercise(A_DEX, FALSE);
  472.             break;
  473.             case 1:
  474.             You("can't control your movements very well."); break;
  475.             case 2:
  476.             pline("It's hard to walk in thin air.");
  477.             exercise(A_DEX, TRUE);
  478.             break;
  479.             }
  480.             return;
  481.         }
  482.  
  483.         /* check slippery ice */
  484.         on_ice = !Levitation && is_ice(u.ux, u.uy);
  485.         if (on_ice) {
  486.             static int skates = 0;
  487.             if (!skates) skates = find_skates();
  488.             if ((uarmf && uarmf->otyp == skates)
  489. #ifdef POLYSELF
  490.             || resists_cold(uasmon) || is_flyer(uasmon)
  491.             || is_floater(uasmon) || is_clinger(uasmon)
  492.             || is_whirly(uasmon)
  493. #endif
  494.                ) on_ice = FALSE;
  495.             else if (!rn2(Cold_resistance ? 3 : 2)) {
  496.             Fumbling |= FROMOUTSIDE;
  497.             if (!(Fumbling & TIMEOUT)) Fumbling += rnd(20);
  498.             }
  499.         }
  500.         if (!on_ice && (Fumbling & FROMOUTSIDE)) {
  501.             Fumbling &= ~FROMOUTSIDE;
  502.             if (!(Fumbling & ~TIMEOUT)) Fumbling = 0;
  503.         }
  504.  
  505.         x = u.ux + u.dx;
  506.         y = u.uy + u.dy;
  507.         if(Stunned || (Confusion && !rn2(5))) {
  508.             register int tries = 0;
  509.  
  510.             do {
  511.                 if(tries++ > 50) {
  512.                     nomul(0);
  513.                     return;
  514.                 }
  515.                 confdir();
  516.                 x = u.ux + u.dx;
  517.                 y = u.uy + u.dy;
  518.             } while(!isok(x, y) || bad_rock(x, y));
  519.         }
  520.         /* turbulence might alter your actual destination */
  521.         if (u.uinwater) {
  522.             water_friction();
  523.             if (!u.dx && !u.dy) {
  524.                 nomul(0);
  525.                 return;
  526.             }
  527.             x = u.ux + u.dx;
  528.             y = u.uy + u.dy;
  529.         }
  530.         if(!isok(x, y)) {
  531.             nomul(0);
  532.             return;
  533.         }
  534.         if((trap = t_at(x, y)) && trap->tseen) {
  535.             if(flags.run >= 2) {
  536.                 nomul(0);
  537.                 flags.move = 0;
  538.                 return;
  539.             } else
  540.                 nomul(0);
  541.         }
  542.             
  543.         if(u.ustuck && (x != u.ustuck->mx ||
  544.                 y != u.ustuck->my)) {
  545.             if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
  546.             /* perhaps it fled (or was teleported or ... ) */
  547.                 u.ustuck = 0;
  548.             } else {
  549. #ifdef POLYSELF
  550.                 /* If polymorphed into a sticking monster,
  551.                  * u.ustuck means it's stuck to you, not you
  552.                  * to it.
  553.                  */
  554.                 if (sticks(uasmon)) {
  555.                     You("release %s.", mon_nam(u.ustuck));
  556.                     u.ustuck = 0;
  557.                 } else {
  558. #endif
  559.                     You("cannot escape from %s!",
  560.                         mon_nam(u.ustuck));
  561.                     nomul(0);
  562.                     return;
  563. #ifdef POLYSELF
  564.                 }
  565. #endif
  566.             }
  567.         }
  568.         mtmp = m_at(x,y);
  569.         if (mtmp) {
  570.             /* Don't attack if you're running, and can see it */
  571.             if (flags.run &&
  572.                 ((!Blind && mon_visible(mtmp) &&
  573.                   ((mtmp->m_ap_type != M_AP_FURNITURE &&
  574.                 mtmp->m_ap_type != M_AP_OBJECT) ||
  575.                    Protection_from_shape_changers)) ||
  576.                  sensemon(mtmp))) {
  577.                 nomul(0);
  578.                 flags.move = 0;
  579.                 return;
  580.             }
  581.         }
  582.     }
  583.  
  584.     u.ux0 = u.ux;
  585.     u.uy0 = u.uy;
  586.     bhitpos.x = x;
  587.     bhitpos.y = y;
  588.     tmpr = &levl[x][y];
  589.  
  590.     /* attack monster */
  591.     if(mtmp) {
  592.         nomul(0);
  593.         /* only attack if we know it's there */
  594.         /* or if it hides_under, in which case we call attack() to print
  595.          * the Wait! message.
  596.          * This is different from ceiling hiders, who aren't handled in
  597.          * attack().
  598.          */
  599.         if(!mtmp->mundetected || sensemon(mtmp) ||
  600.             (hides_under(mtmp->data) && !is_safepet(mtmp))){
  601.         gethungry();
  602.         if(wtcap >= HVY_ENCUMBER && moves%3) {
  603.             if(u.uhp > 1)
  604.             u.uhp--;
  605.             else {
  606.             pline("You pass out from exertion!");
  607.             exercise(A_CON, FALSE);
  608.             nomul(-10);
  609.             u.usleep = 1;
  610.             }
  611.         }
  612.         if(multi < 0) return;    /* we just fainted */
  613.  
  614.         /* try to attack; note that it might evade */
  615.         /* also, we don't attack tame when _safepet_ */
  616.         if(attack(mtmp)) return;
  617.         }
  618.     }
  619.  
  620.     /* not attacking an animal, so we try to move */
  621. #ifdef POLYSELF
  622.     if(!uasmon->mmove) {
  623.         You("are rooted %s.",
  624.             Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
  625.             "in place" : "to the ground");
  626.         nomul(0);
  627.         return;
  628.     }
  629. #endif
  630.     if(u.utrap) {
  631.         if(u.utraptype == TT_PIT) {
  632.             if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) {
  633.             Your("%s gets stuck in a crevice.", body_part(LEG));
  634.             display_nhwindow(WIN_MESSAGE, FALSE);
  635.             clear_nhwindow(WIN_MESSAGE);
  636.             You("free your %s.", body_part(LEG));
  637.             } else if (!(--u.utrap)) {
  638.             You("crawl to the edge of the pit.");
  639.             fill_pit(u.ux, u.uy);
  640.             vision_full_recalc = 1;    /* vision limits change */
  641.             } else if (flags.verbose) 
  642.             Norep( (Hallucination && !rn2(5)) ?
  643.                 "You've fallen, and you can't get up." :
  644.                 "You are still in a pit." );
  645.         } else if (u.utraptype == TT_LAVA) {
  646.             if(flags.verbose)
  647.                 Norep("You are stuck in the lava.");
  648.             if(!is_lava(x,y)) {
  649.             u.utrap--;
  650.             if((u.utrap & 0xff) == 0) {
  651.                 You("pull yourself to the edge of the lava.");
  652.                 u.utrap = 0;
  653.             }
  654.             }
  655.             u.umoved = TRUE;
  656.         } else if (u.utraptype == TT_WEB) {
  657.             if(--u.utrap) {
  658.             if(flags.verbose)
  659.                 Norep("You are stuck to the web.");
  660.             } else You("disentangle yourself.");
  661.         } else if (u.utraptype == TT_INFLOOR) {
  662.             if(--u.utrap) {
  663.             if(flags.verbose)
  664.                 Norep("You are stuck in the floor.");
  665.             } else You("finally wiggle free.");
  666.         } else {
  667.             if(flags.verbose)
  668.             Norep("You are caught in a bear trap.");
  669.             if((u.dx && u.dy) || !rn2(5)) u.utrap--;
  670.         }
  671.         return;
  672.     }
  673.  
  674.  
  675.     /*
  676.      *  Check for physical obstacles.  First, the place we are going.
  677.      */
  678.     if (IS_ROCK(tmpr->typ)) {
  679.         if (Blind) feel_location(x,y);
  680. #ifdef POLYSELF
  681.         if (passes_walls(uasmon) && may_passwall(x,y)) {
  682.         ;    /* do nothing */
  683.         } else if (tunnels(uasmon) && !needspick(uasmon)) {
  684.         /* Eat the rock. */
  685.         if (still_chewing(x,y)) return;
  686.         } else {
  687. #endif
  688.         if (Is_stronghold(&u.uz) && is_db_wall(x,y))
  689.             pline("The drawbridge is up!");
  690.         flags.move = 0;
  691.         nomul(0);
  692.         return;
  693. #ifdef POLYSELF
  694.         }
  695. #endif
  696.     } else if (IS_DOOR(tmpr->typ)) {
  697.         if (closed_door(x,y)) {
  698.         if (Blind) feel_location(x,y);
  699. #ifdef POLYSELF
  700.         if (passes_walls(uasmon))
  701.             ;    /* do nothing */
  702.         else if (amorphous(uasmon))
  703.             You("ooze under the door.");
  704.         else if (tunnels(uasmon) && !needspick(uasmon)) {
  705.             /* Eat the door. */
  706.             if (still_chewing(x,y)) return;
  707.         } else {
  708. #endif
  709.             flags.move = 0;
  710.             if (x == u.ux || y == u.uy) {
  711.             if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
  712.                 pline("Ouch!  You bump into a door.");
  713.                 exercise(A_DEX, FALSE);
  714.             } else pline("That door is closed.");
  715.             }
  716.             nomul(0);
  717.             return;
  718. #ifdef POLYSELF
  719.         }
  720. #endif
  721.         } else if (u.dx && u.dy
  722. #ifdef POLYSELF
  723.             && !passes_walls(uasmon)
  724. #endif
  725.             && ((tmpr->doormask & ~D_BROKEN)
  726. #ifdef REINCARNATION
  727.                     || Is_rogue_level(&u.uz)
  728. #endif
  729.                     || block_door(x,y))) {
  730.         /* Diagonal moves into a door are not allowed. */
  731.         if (Blind) feel_location(x,y);    /* ?? */
  732.         flags.move = 0;
  733.         nomul(0);
  734.         return;
  735.         }
  736.     }
  737.     if (u.dx && u.dy && bad_rock(u.ux,y) && bad_rock(x,u.uy)) {
  738.         /* Move at a diagonal. */
  739. #ifdef POLYSELF
  740.         if (bigmonst(uasmon)) {
  741.         Your("body is too large to fit through.");
  742.         nomul(0);
  743.         return;
  744.         }
  745. #endif
  746.         if (invent && inv_weight() > -400) {
  747.         You("are carrying too much to get through.");
  748.         nomul(0);
  749.         return;
  750.         }
  751.     }
  752.  
  753.     ust = &levl[u.ux][u.uy];
  754.  
  755.     /* Now see if other things block our way . . */
  756.     if (u.dx && u.dy
  757. #ifdef POLYSELF
  758.              && !passes_walls(uasmon)
  759. #endif
  760.              && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)
  761. #ifdef REINCARNATION
  762.                  || Is_rogue_level(&u.uz)
  763. #endif
  764.                  || block_entry(x, y))
  765.                  )) {
  766.         /* Can't move at a diagonal out of a doorway with door. */
  767.         flags.move = 0;
  768.         nomul(0);
  769.         return;
  770.     }
  771.  
  772.     if (sobj_at(BOULDER,x,y)
  773. #ifdef POLYSELF
  774.                 && !passes_walls(uasmon)
  775. #endif
  776.                             ) {
  777.         if (!(Blind || Hallucination) && (flags.run >= 2)) {
  778.         nomul(0);
  779.         flags.move = 0;
  780.         return;
  781.         }
  782. #ifdef POLYSELF
  783.         /* tunneling monsters will chew before pushing */
  784.         if (tunnels(uasmon) && !needspick(uasmon)) {
  785.         if (still_chewing(x,y)) return;
  786.         } else
  787. #endif
  788.         if (moverock() < 0) return;
  789.     }
  790.  
  791.     /* OK, it is a legal place to move. */
  792.  
  793.     /* Move ball and chain.  */
  794.     if (Punished)
  795.         if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy))
  796.         return;
  797.  
  798.     /* now move the hero */
  799.     mtmp = m_at(x, y);
  800.     u.ux += u.dx;
  801.     u.uy += u.dy;
  802.     /* if safepet at destination then move the pet to the hero's
  803.      * previous location using the same conditions as in attack().
  804.      * there are special extenuating circumstances:
  805.      * (1) if the pet dies then your god angers,
  806.      * (2) if the pet gets trapped then your god may disapprove,
  807.      * (3) if the pet was already trapped and you attempt to free it
  808.      * not only do you encounter the trap but you may frighten your
  809.      * pet causing it to go wild!  moral: don't abuse this privilege.
  810.      */
  811.     /* Ceiling-hiding pets are skipped by this section of code, to
  812.      * be caught by the normal falling-monster code.
  813.      */
  814.     if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
  815.         int swap_result;
  816.  
  817.         /* if trapped, there's a chance the pet goes wild */
  818.         if (mtmp->mtrapped) {
  819.             if (!rn2(mtmp->mtame)) {
  820.             mtmp->mtame = mtmp->mpeaceful = mtmp->msleep = 0;
  821. #ifndef SOUNDS
  822.             pline ("%s suddenly goes wild!",
  823.                    mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp));
  824. #else
  825.                 growl(mtmp);
  826.             } else {
  827.                 yelp(mtmp);
  828. #endif
  829.             }
  830.             }
  831.  
  832.         if(!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
  833.  
  834.         mtmp->mtrapped = 0;
  835.         mtmp->mundetected = 0;
  836.         remove_monster(x, y);
  837.         place_monster(mtmp, u.ux0, u.uy0);
  838.  
  839.         /* check first to see if monster drowned.
  840.          * then check for traps.
  841.          */
  842.         if (minwater(mtmp)) {
  843.             swap_result = 2;
  844.         } else swap_result = mintrap(mtmp);
  845.  
  846.         switch (swap_result) {
  847.         case 0:
  848.             You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
  849.                 mtmp->mnamelth ? NAME(mtmp) : mon_nam(mtmp));
  850.             break;
  851.         case 1:    /* trapped */
  852.         case 3: /* changed levels */
  853.             /* there's already been a trap message, reinforce it */
  854.             abuse_dog(mtmp);
  855. #ifndef SOUNDS    /* else complaint from abuse_dog() */
  856.             pline("Trapping your pet was a selfish move.");
  857. #endif
  858.             adjalign(-3);
  859.             break;
  860.         case 2:
  861.             /* it may have drowned or died.  that's no way to
  862.              * treat a pet!  your god gets angry and complains.
  863.              */
  864.             if (rn2(4)) {
  865.             pline ("%s complains in a booming voice:", u_gname());
  866.             verbalize("Losing your pet like this was a mistake!");
  867.             u.ugangr++;
  868.             adjalign(-15);
  869.             }
  870.             break;
  871.         default:
  872.             pline("that's strange, unknown mintrap result!");
  873.             break;
  874.         }
  875.     }
  876.  
  877.     reset_occupations();
  878.     if(flags.run) {
  879.         if(IS_DOOR(tmpr->typ) ||
  880. #ifdef POLYSELF
  881.         (IS_ROCK(tmpr->typ)) ||
  882. #endif
  883.         (xupstair == u.ux && yupstair == u.uy) ||
  884.         (xdnstair == u.ux && ydnstair == u.uy)
  885.         || (sstairs.sx == u.ux && sstairs.sy == u.uy)
  886.         || (xupladder == u.ux && yupladder == u.uy)
  887.         || (xdnladder == u.ux && ydnladder == u.uy)
  888.         || IS_FOUNTAIN(tmpr->typ)
  889.         || IS_THRONE(tmpr->typ)
  890. #ifdef SINKS
  891.         || IS_SINK(tmpr->typ)
  892. #endif
  893.         || IS_ALTAR(tmpr->typ)
  894.         )
  895.             nomul(0);
  896.     }
  897. #ifdef POLYSELF
  898.     if (hides_under(uasmon))
  899.         u.uundetected = OBJ_AT(u.ux, u.uy);
  900.     else if (u.dx || u.dy) { /* piercer */
  901.         if (u.usym == S_MIMIC_DEF)
  902.         u.usym = S_MIMIC;
  903.         u.uundetected = 0;
  904.     }
  905. #endif
  906.  
  907. #ifdef WALKIES
  908.     check_leash(u.ux0,u.uy0);
  909. #endif
  910.     if(u.ux0 != u.ux || u.uy0 != u.uy) {
  911.         u.umoved = TRUE;
  912.         /* Clean old position -- vision_recalc() will print our new one. */
  913.         newsym(u.ux0,u.uy0);
  914.         /* Since the hero has moved, adjust what can be seen/unseen. */
  915.         vision_recalc(1);    /* Do the work now in the recover time. */
  916.  
  917.         /* a special clue-msg when on the Invocation position */
  918.         if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
  919.             register struct obj *otmp;
  920.  
  921.             You("feel a strange vibration under your %s.",
  922.             makeplural(body_part(FOOT)));
  923.  
  924.         for(otmp = invent; otmp; otmp = otmp->nobj) {
  925.                 if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
  926.                otmp->spe == 7 && otmp->lamplit) {
  927.                       pline("%s glows with a strange light!",
  928.                 The(xname(otmp)));
  929.               break;
  930.                }
  931.             }
  932.         
  933.         }
  934.     }
  935.  
  936.     if (Punished)                /* put back ball and chain */
  937.         move_bc(0,bc_control,ballx,bally,chainx,chainy);
  938.  
  939.     spoteffects();
  940. }
  941.  
  942. #endif /* OVL3 */
  943. #ifdef OVL2
  944.  
  945. void
  946. spoteffects()
  947. {
  948.     register struct trap *trap;
  949.     register struct monst *mtmp;
  950.  
  951.     if(u.uinwater) {
  952.         int was_underwater;
  953.  
  954.         if (!is_pool(u.ux,u.uy)) {
  955.             if (Is_waterlevel(&u.uz))
  956.                 You("pop into an air bubble.");
  957.             else if (is_lava(u.ux, u.uy))
  958.                 You("leave the water...");    /* oops! */
  959.             else
  960.                 You("are on solid %s again.",
  961.                     is_ice(u.ux, u.uy) ? "ice" : "land");
  962.         }
  963.         else if (Is_waterlevel(&u.uz))
  964.             goto stillinwater;
  965.         else if (Levitation)
  966.             You("pop out of the water like a cork!");
  967. #ifdef POLYSELF
  968.         else if (is_flyer(uasmon))
  969.             You("fly out of the water.");
  970. #endif
  971.         else if (Wwalking)
  972.             You("slowly rise above the surface.");
  973.         else
  974.             goto stillinwater;
  975.         was_underwater = Underwater && !Is_waterlevel(&u.uz);
  976.         u.uinwater = 0;        /* leave the water */
  977.         if (was_underwater) {    /* restore vision */
  978.             docrt();
  979.             vision_full_recalc = 1;
  980.         }
  981.     }
  982. stillinwater:;
  983.     if(!Levitation && !u.ustuck
  984. #ifdef POLYSELF
  985.        && !is_flyer(uasmon)
  986. #endif
  987.        ) {
  988.         /* limit recursive calls through teleds() */
  989.         if(is_lava(u.ux,u.uy) && lava_effects())
  990.             return;
  991.         if(is_pool(u.ux,u.uy) && !Wwalking && drown())
  992.             return;
  993.     }
  994.     check_special_room(FALSE);
  995. #ifdef SINKS
  996.     if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
  997.         dosinkfall();
  998. #endif
  999.     pickup(1);
  1000.     if ((trap = t_at(u.ux,u.uy)) != 0)
  1001.         dotrap(trap);    /* fall into pit, arrow trap, etc. */
  1002.     if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
  1003.         mtmp->mundetected = 0;
  1004.         switch(mtmp->data->mlet) {
  1005.             case S_PIERCER:
  1006.             pline("%s suddenly drops from the ceiling!",
  1007.                   Amonnam(mtmp));
  1008.             if(mtmp->mtame) /* jumps to greet you, not attack */
  1009.                 ;
  1010.             else if(uarmh)
  1011.                 pline("Its blow glances off your helmet.");
  1012.             else if (u.uac + 3 <= rnd(20))
  1013.                 You("are almost hit by %s!",
  1014.                 x_monnam(mtmp, 2, "falling", 1));
  1015.             else {
  1016.                 int dmg;
  1017.                 You("are hit by %s!",
  1018.                 x_monnam(mtmp, 2, "falling", 1));
  1019.                 dmg = d(4,6);
  1020.                 if(Half_physical_damage) dmg = (dmg+1) / 2;
  1021.                 mdamageu(mtmp, dmg);
  1022.             }
  1023.             break;
  1024.             default:    /* monster surprises you. */
  1025.             if(mtmp->mtame)
  1026.                 pline("%s jumps near you from the ceiling.",
  1027.                     Amonnam(mtmp));
  1028.             else if(mtmp->mpeaceful) {
  1029.                 You("surprise %s!",
  1030.                     Blind && !sensemon(mtmp) ?
  1031.                     "something" : a_monnam(mtmp));
  1032.                 mtmp->mpeaceful = 0;
  1033.             } else
  1034.                 pline("%s attacks you by surprise!",
  1035.                     Amonnam(mtmp));
  1036.             break;
  1037.         }
  1038.         mnexto(mtmp); /* have to move the monster */
  1039.     }
  1040. }
  1041.  
  1042. STATIC_OVL boolean
  1043. monstinroom(mdat,roomno)
  1044. struct permonst *mdat;
  1045. int roomno;
  1046. {
  1047.     register struct monst *mtmp;
  1048.  
  1049.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1050.         if(mtmp->data == mdat && 
  1051.            index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
  1052.             return(TRUE);
  1053.     return(FALSE);
  1054. }
  1055.  
  1056. char *
  1057. in_rooms(x, y, typewanted)
  1058. register xchar x, y;
  1059. register int typewanted;
  1060. {
  1061.     static char buf[5];
  1062.     char rno, *ptr = &buf[4];
  1063.     int typefound, min_x, min_y, max_x, max_y_offset, step;
  1064.     register struct rm *lev;
  1065.  
  1066. #define goodtype(rno) (!typewanted || \
  1067.          ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
  1068.          ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
  1069.  
  1070.     switch (rno = levl[x][y].roomno) { 
  1071.         case NO_ROOM:
  1072.             return(ptr);
  1073.         case SHARED:
  1074.             step = 2;
  1075.             break;
  1076.         case SHARED_PLUS:
  1077.             step = 1;
  1078.             break;
  1079.         default:            /* i.e. a regular room # */
  1080.             if (goodtype(rno)) 
  1081.                 *(--ptr) = rno;
  1082.             return(ptr);
  1083.     }
  1084.  
  1085.     min_x = x - 1;
  1086.     max_x = x + 1;
  1087.     if (x < 1)
  1088.         min_x += step;
  1089.     else 
  1090.     if (x >= COLNO)
  1091.         max_x -= step;
  1092.  
  1093.     min_y = y - 1;
  1094.     max_y_offset = 2;
  1095.     if (min_y < 0) {
  1096.         min_y += step;
  1097.         max_y_offset -= step;
  1098.     } else
  1099.     if ((min_y + max_y_offset) >= ROWNO)
  1100.         max_y_offset -= step;
  1101.  
  1102.     for (x = min_x; x <= max_x; x += step) {
  1103.         lev = &levl[x][min_y];
  1104.         y = 0;
  1105.         if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1106.             !index(ptr, rno) && goodtype(rno)) 
  1107.             *(--ptr) = rno;
  1108.         y += step;
  1109.         if (y > max_y_offset)
  1110.             continue;
  1111.         if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1112.                  !index(ptr, rno) && goodtype(rno))
  1113.             *(--ptr) = rno;
  1114.         y += step;
  1115.         if (y > max_y_offset)
  1116.             continue;
  1117.         if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1118.             !index(ptr, rno) && goodtype(rno))
  1119.             *(--ptr) = rno;
  1120.     }
  1121.     return(ptr);
  1122. }
  1123.  
  1124. static void 
  1125. move_update(newlev)
  1126. register boolean newlev;
  1127. {
  1128.     char *ptr1, *ptr2, *ptr3, *ptr4;
  1129.  
  1130.     Strcpy(u.urooms0, u.urooms);
  1131.     Strcpy(u.ushops0, u.ushops);
  1132.     if (newlev) {
  1133.         u.urooms[0] = '\0';
  1134.         u.uentered[0] = '\0';
  1135.         u.ushops[0] = '\0';
  1136.         u.ushops_entered[0] = '\0';
  1137.         Strcpy(u.ushops_left, u.ushops0);
  1138.         return;
  1139.     } 
  1140.     Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
  1141.  
  1142.     for (ptr1 = &u.urooms[0], 
  1143.          ptr2 = &u.uentered[0], 
  1144.          ptr3 = &u.ushops[0],
  1145.          ptr4 = &u.ushops_entered[0]; 
  1146.          *ptr1; ptr1++) {
  1147.         if (!index(u.urooms0, *ptr1))
  1148.             *(ptr2++) = *ptr1;    
  1149.         if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
  1150.             *(ptr3++) = *ptr1;
  1151.             if (!index(u.ushops0, *ptr1))
  1152.                 *(ptr4++) = *ptr1;
  1153.         }
  1154.     }
  1155.     *ptr2 = '\0';
  1156.     *ptr3 = '\0';
  1157.     *ptr4 = '\0';
  1158.  
  1159.     /* filter u.ushops0 -> u.ushops_left */
  1160.     for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
  1161.         if (!index(u.ushops, *ptr1))
  1162.             *(ptr2++) = *ptr1;
  1163.     *ptr2 = '\0';
  1164. }
  1165.  
  1166. void
  1167. check_special_room(newlev) 
  1168. register boolean newlev;
  1169. {
  1170.     register struct monst *mtmp;
  1171.     char *ptr;
  1172.  
  1173.     move_update(newlev);
  1174.  
  1175.     if (*u.ushops0)
  1176.         u_left_shop(u.ushops_left, newlev);
  1177.  
  1178.     if (!*u.uentered && !*u.ushops_entered)     /* implied by newlev */
  1179.         return;        /* no entrance messages necessary */
  1180.  
  1181.     /* Did we just enter a shop? */
  1182.     if (*u.ushops_entered)
  1183.             u_entered_shop(u.ushops_entered);
  1184.  
  1185.     for (ptr = &u.uentered[0]; *ptr; ptr++) {
  1186.         register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
  1187.  
  1188.         /* Did we just enter some other special room? */
  1189.         /* vault.c insists that a vault remain a VAULT,
  1190.          * and temples should remain TEMPLEs,
  1191.          * but everything else gives a message only the first time */
  1192.         switch (rt) {
  1193.         case ZOO:
  1194.             pline("Welcome to David's treasure zoo!");
  1195.             break;
  1196.         case SWAMP:
  1197.             pline("It %s rather %s down here.",
  1198.               Blind ? "feels" : "looks",
  1199.               Blind ? "humid" : "muddy");
  1200.             break;
  1201.         case COURT:
  1202.             You("enter an opulent throne room!");
  1203.             break;
  1204.         case MORGUE:
  1205.             if(midnight()) {
  1206. #ifdef POLYSELF
  1207.             const char *run = locomotion(uasmon, "Run");
  1208.             pline("%s away!  %s away!", run, run);
  1209. #else
  1210.             pline("Run away!  Run away!");
  1211. #endif
  1212.             } else
  1213.             You("have an uncanny feeling...");
  1214.             break;
  1215.         case BEEHIVE:
  1216.             You("enter a giant beehive!");
  1217.             break;
  1218. #ifdef ARMY
  1219.         case BARRACKS:
  1220.             if(monstinroom(&mons[PM_SOLDIER], roomno) ||
  1221.             monstinroom(&mons[PM_SERGEANT], roomno) ||
  1222.             monstinroom(&mons[PM_LIEUTENANT], roomno) ||
  1223.             monstinroom(&mons[PM_CAPTAIN], roomno))
  1224.             You("enter a military barracks!");
  1225.             else 
  1226.             You("enter an abandoned barracks.");
  1227.             break;
  1228. #endif
  1229.         case DELPHI:
  1230.             if(monstinroom(&mons[PM_ORACLE], roomno))
  1231.             verbalize("Hello, %s, welcome to Delphi!", plname);
  1232.             break;
  1233.         case TEMPLE:
  1234.             intemple(roomno + ROOMOFFSET);
  1235.             /* fall through */
  1236.         default:
  1237.             rt = 0;
  1238.         } 
  1239.  
  1240.         if (rt != 0) {
  1241.         rooms[roomno].rtype = OROOM;
  1242.         if (!search_special(rt)) {
  1243.             /* No more room of that type */
  1244.             switch(rt) {
  1245.                 case COURT:
  1246.                 level.flags.has_court = 0;
  1247.                 break;
  1248.                 case SWAMP:
  1249.                 level.flags.has_swamp = 0;
  1250.                 break;
  1251.                 case MORGUE:
  1252.                 level.flags.has_morgue = 0;
  1253.                 break;
  1254.                 case ZOO:
  1255.                 level.flags.has_zoo = 0;
  1256.                 break;
  1257. #ifdef ARMY
  1258.                 case BARRACKS:
  1259.                 level.flags.has_barracks = 0;
  1260.                 break;
  1261. #endif
  1262.                 case TEMPLE:
  1263.                 level.flags.has_temple = 0;
  1264.                 break;
  1265.                 case BEEHIVE:
  1266.                 level.flags.has_beehive = 0;
  1267.                 break;
  1268.             }
  1269.         }
  1270.         if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
  1271.             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1272.                 if(!Stealth && !rn2(3))
  1273.                     mtmp->msleep = 0;
  1274.         }
  1275.     }
  1276.  
  1277.     return;
  1278. }
  1279.  
  1280. #endif /* OVL2 */
  1281. #ifdef OVLB
  1282.  
  1283. int
  1284. dopickup()
  1285. {
  1286.     int count;
  1287.     /* awful kludge to work around parse()'s pre-decrement */
  1288.     count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
  1289.     multi = 0;    /* always reset */
  1290.     /* uswallow case added by GAN 01/29/87 */
  1291.     if(u.uswallow) {
  1292.         if (is_animal(u.ustuck->data)) {
  1293.             You("pick up %s tongue.", 
  1294.                         s_suffix(mon_nam(u.ustuck)));
  1295.             pline("But it's kind of slimy, so you drop it.");
  1296.         } else
  1297.             You("don't %s anything in here to pick up.",
  1298.               Blind ? "feel" : "see");
  1299.         return(1);
  1300.     }
  1301.     if(is_pool(u.ux, u.uy)) {
  1302.         if(Wwalking
  1303. #ifdef POLYSELF
  1304.            || is_flyer(uasmon) || is_clinger(uasmon)
  1305. #endif
  1306.            ) {
  1307.             You("cannot dive into the water to pick things up.");
  1308.             return(1);
  1309.         }
  1310.         else if(!Underwater) {
  1311.             You("can't even see the bottom, let alone pick up something.");
  1312.             return(1);
  1313.         }
  1314.     }
  1315.     if(!OBJ_AT(u.ux, u.uy)) {
  1316.         pline("There is nothing here to pick up.");
  1317.         return(0);
  1318.     }
  1319.     if(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
  1320.         You("cannot reach the %s.", surface(u.ux,u.uy));
  1321.         return(1);
  1322.     }
  1323.     pickup(-count);
  1324.     return(1);
  1325. }
  1326.  
  1327. #endif /* OVLB */
  1328. #ifdef OVL2
  1329.  
  1330. /* stop running if we see something interesting */
  1331. /* turn around a corner if that is the only way we can proceed */
  1332. /* do not turn left or right twice */
  1333. void
  1334. lookaround()
  1335. {
  1336.     register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
  1337.     register int corrct = 0, noturn = 0;
  1338.     register struct monst *mtmp;
  1339.     register struct trap *trap;
  1340.  
  1341. #ifdef POLYSELF
  1342.     /* Grid bugs stop if trying to move diagonal, even if blind.  Maybe */
  1343.     /* they polymorphed while in the middle of a long move. */
  1344.     if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
  1345.         nomul(0);
  1346.         return;
  1347.     }
  1348. #endif
  1349.     if(Blind || flags.run == 0) return;
  1350.     for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
  1351.         if(!isok(x,y)) continue;
  1352. #ifdef POLYSELF
  1353.     if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
  1354. #endif
  1355.     if(x == u.ux && y == u.uy) continue;
  1356.  
  1357.     if((mtmp = m_at(x,y)) &&
  1358.             mtmp->m_ap_type != M_AP_FURNITURE &&
  1359.             mtmp->m_ap_type != M_AP_OBJECT &&
  1360.             (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
  1361.         if((flags.run != 1 && !mtmp->mtame)
  1362.                     || (x == u.ux+u.dx && y == u.uy+u.dy))
  1363.         goto stop;
  1364.     }
  1365.  
  1366.     if (levl[x][y].typ == STONE) continue;
  1367.     if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
  1368.  
  1369.     if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
  1370.         IS_AIR(levl[x][y].typ))
  1371.         continue;
  1372.     else if (closed_door(x,y)) {
  1373.         if(x != u.ux && y != u.uy) continue;
  1374.         if(flags.run != 1) goto stop;
  1375.         goto bcorr;
  1376.     } else if (levl[x][y].typ == CORR) {
  1377. bcorr:
  1378.         if(levl[u.ux][u.uy].typ != ROOM) {
  1379.         if(flags.run == 1 || flags.run == 3) {
  1380.             i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
  1381.             if(i > 2) continue;
  1382.             if(corrct == 1 && dist2(x,y,x0,y0) != 1)
  1383.             noturn = 1;
  1384.             if(i < i0) {
  1385.             i0 = i;
  1386.             x0 = x;
  1387.             y0 = y;
  1388.             m0 = mtmp ? 1 : 0;
  1389.             }
  1390.         }
  1391.         corrct++;
  1392.         }
  1393.         continue;
  1394.     } else if ((trap = t_at(x,y)) && trap->tseen) {
  1395.         if(flags.run == 1) goto bcorr;    /* if you must */
  1396.         if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  1397.         continue;
  1398.     } else if (is_pool(x,y) || is_lava(x,y)) {
  1399.         /* water and lava only stop you if directly in front, and stop
  1400.          * you even if you are running
  1401.          */
  1402.         if(!Levitation &&
  1403. #ifdef POLYSELF
  1404.             !is_flyer(uasmon) && !is_clinger(uasmon) &&
  1405. #endif
  1406.             /* No Wwalking check; otherwise they'd be able
  1407.              * to test boots by trying to SHIFT-direction
  1408.              * into a pool and seeing if the game allowed it
  1409.              */
  1410.             x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  1411.         continue;
  1412.     } else {        /* e.g. objects or trap or stairs */
  1413.         if(flags.run == 1) goto bcorr;
  1414.         if(mtmp) continue;        /* d */
  1415.         if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
  1416.            ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
  1417.            continue;
  1418.     }
  1419. stop:
  1420.     nomul(0);
  1421.     return;
  1422.     } /* end for loops */
  1423.  
  1424.     if(corrct > 1 && flags.run == 2) goto stop;
  1425.     if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
  1426.                 (corrct == 1 || (corrct == 2 && i0 == 1))) {
  1427.     /* make sure that we do not turn too far */
  1428.     if(i0 == 2) {
  1429.         if(u.dx == y0-u.uy && u.dy == u.ux-x0)
  1430.         i = 2;        /* straight turn right */
  1431.         else
  1432.         i = -2;        /* straight turn left */
  1433.     } else if(u.dx && u.dy) {
  1434.         if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
  1435.         i = -1;        /* half turn left */
  1436.         else
  1437.         i = 1;        /* half turn right */
  1438.     } else {
  1439.         if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
  1440.         i = 1;        /* half turn right */
  1441.         else
  1442.         i = -1;        /* half turn left */
  1443.     }
  1444.  
  1445.     i += u.last_str_turn;
  1446.     if(i <= 2 && i >= -2) {
  1447.         u.last_str_turn = i;
  1448.         u.dx = x0-u.ux;
  1449.         u.dy = y0-u.uy;
  1450.     }
  1451.     }
  1452. }
  1453.  
  1454. /* something like lookaround, but we are not running */
  1455. /* react only to monsters that might hit us */
  1456. int
  1457. monster_nearby()
  1458. {
  1459.     register int x,y;
  1460.     register struct monst *mtmp;
  1461.  
  1462.     if(!Blind)
  1463.     for(x = u.ux-1; x <= u.ux+1; x++)
  1464.         for(y = u.uy-1; y <= u.uy+1; y++) {
  1465.         if(!isok(x,y)) continue;
  1466.         if(x == u.ux && y == u.uy) continue;
  1467.         if((mtmp = m_at(x,y)) &&
  1468.            mtmp->m_ap_type != M_AP_FURNITURE &&
  1469.            mtmp->m_ap_type != M_AP_OBJECT &&
  1470.            !mtmp->mpeaceful &&
  1471.            (!is_hider(mtmp->data) || !mtmp->mundetected) &&
  1472.            !noattacks(mtmp->data) &&
  1473.            mtmp->mcanmove && !mtmp->msleep &&  /* aplvax!jcn */
  1474.            (!mtmp->minvis || See_invisible) &&
  1475.            !onscary(u.ux, u.uy, mtmp))
  1476.             return(1);
  1477.     }
  1478.     return(0);
  1479. }
  1480.  
  1481. void
  1482. nomul(nval)
  1483.     register int nval;
  1484. {
  1485.     if(multi < nval) return;    /* This is a bug fix by ab@unido */
  1486.     u.uinvulnerable = FALSE;    /* Kludge to avoid ctrl-C bug -dlc */
  1487.     u.usleep = 0;
  1488.     multi = nval;
  1489.     flags.mv = flags.run = 0;
  1490. }
  1491.  
  1492. #endif /* OVL2 */
  1493. #ifdef OVL1
  1494.  
  1495. void
  1496. losehp(n, knam, k_format)
  1497. register int n;
  1498. register const char *knam;
  1499. boolean k_format;
  1500. {
  1501. #ifdef POLYSELF
  1502.     if (u.mtimedone) {
  1503.         u.mh -= n;
  1504.         if (u.mhmax < u.mh) u.mhmax = u.mh;
  1505.         flags.botl = 1;
  1506.         if (u.mh < 1) rehumanize();
  1507.         return;
  1508.     }
  1509. #endif
  1510.     u.uhp -= n;
  1511.     if(u.uhp > u.uhpmax)
  1512.         u.uhpmax = u.uhp;    /* perhaps n was negative */
  1513.     flags.botl = 1;
  1514.     if(u.uhp < 1) {
  1515.         killer_format = k_format;
  1516.         killer = knam;        /* the thing that killed you */
  1517.         You("die...");
  1518.         done(DIED);
  1519.     } else if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0){
  1520.         wailmsg = moves;
  1521.         if(index("WEV", pl_character[0])) {
  1522.             if (u.uhp == 1)
  1523.                 pline("%s is about to die.", pl_character);
  1524.             else if (4 <= (!!(HTeleportation & INTRINSIC)) +
  1525.                     (!!(HSee_invisible & INTRINSIC)) +
  1526.                     (!!(HPoison_resistance & INTRINSIC)) +
  1527.                     (!!(HCold_resistance & INTRINSIC)) +
  1528.                     (!!(HShock_resistance & INTRINSIC)) +
  1529.                     (!!(HFire_resistance & INTRINSIC)) +
  1530.                     (!!(HSleep_resistance & INTRINSIC)) +
  1531.                     (!!(HDisint_resistance & INTRINSIC)) +
  1532.                     (!!(HTeleport_control & INTRINSIC)) +
  1533.                     (!!(Stealth & INTRINSIC)) +
  1534.                     (!!(Fast & INTRINSIC)) +
  1535.                     (!!(HInvis & INTRINSIC)))
  1536.                 pline("%s, all your powers will be lost...",
  1537.                     pl_character);
  1538.             else
  1539.                 pline("%s, your life force is running out.",
  1540.                     pl_character);
  1541.         } else {
  1542.             if(u.uhp == 1)
  1543.                 You("hear the wailing of the Banshee...");
  1544.             else
  1545.                 You("hear the howling of the CwnAnnwn...");
  1546.         }
  1547.     }
  1548. }
  1549.  
  1550. int
  1551. weight_cap()
  1552. {
  1553.     register long carrcap;
  1554.  
  1555.     carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50;
  1556. #ifdef POLYSELF
  1557.     if (u.mtimedone) {
  1558.         /* consistent with can_carry() in mon.c */
  1559.         if (u.usym == S_NYMPH)
  1560.                 carrcap = MAX_CARR_CAP;
  1561.         else if (!uasmon->cwt)
  1562.             carrcap = (carrcap * (long)uasmon->msize) / MZ_HUMAN;
  1563.         else if (!strongmonst(uasmon)
  1564.             || (strongmonst(uasmon) && (uasmon->cwt > WT_HUMAN)))
  1565.             carrcap = (carrcap * (long)uasmon->cwt / WT_HUMAN);
  1566.     }
  1567. #endif
  1568.     if(Levitation || Is_airlevel(&u.uz))    /* pugh@cornell */
  1569.         carrcap = MAX_CARR_CAP;
  1570.     else {
  1571.         if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
  1572. #ifdef POLYSELF
  1573.         if (!is_flyer(uasmon))
  1574. #endif
  1575.                     {
  1576.             if(Wounded_legs & LEFT_SIDE) carrcap -= 100;
  1577.             if(Wounded_legs & RIGHT_SIDE) carrcap -= 100;
  1578.         }
  1579.         if (carrcap < 0) carrcap = 0;
  1580.     }
  1581.     return((int) carrcap);
  1582. }
  1583.  
  1584. /* returns how far beyond the normal capacity the player is currently. */
  1585. /* inv_weight() is negative if the player is below normal capacity. */
  1586. int
  1587. inv_weight()
  1588. {
  1589.     register struct obj *otmp = invent;
  1590. #ifdef LINT    /* long to int conversion */
  1591.     register int wt = 0;
  1592. #else
  1593.     register int wt = (int)((u.ugold + 50L)/100L);
  1594. #endif /* LINT */
  1595.     while(otmp){
  1596. #ifdef POLYSELF
  1597.         if (otmp->otyp != BOULDER || !throws_rocks(uasmon))
  1598. #endif
  1599.             wt += otmp->owt;
  1600.         otmp = otmp->nobj;
  1601.     }
  1602.     return(wt - weight_cap());
  1603. }
  1604.  
  1605. /*
  1606.  * Returns 0 if below normal capacity, or the number of "capacity units"
  1607.  * over the normal capacity the player is loaded.  Max is 5.
  1608.  */
  1609. int
  1610. near_capacity()
  1611. {
  1612.     int cap, wt = inv_weight(), wc = weight_cap();
  1613.  
  1614.     if (wt <= 0) return UNENCUMBERED;
  1615.     if (wc <= 1) return OVERLOADED;
  1616.     cap = (wt*2 / wc) + 1;
  1617.     return min(cap, OVERLOADED);
  1618. }
  1619.  
  1620. int
  1621. max_capacity()
  1622. {
  1623.     return(inv_weight() - (2 * weight_cap()));
  1624. }
  1625.  
  1626. boolean
  1627. check_capacity(str)
  1628. const char *str;
  1629. {
  1630.     if(near_capacity() >= EXT_ENCUMBER) {
  1631.     if(str)
  1632.         pline(str);
  1633.     else
  1634.         You("can't do that while carrying so much stuff.");
  1635.     return 1;
  1636.     }
  1637.     return 0;
  1638. }
  1639.  
  1640. #endif /* OVL1 */
  1641. #ifdef OVLB
  1642.  
  1643. int
  1644. inv_cnt()
  1645. {
  1646.     register struct obj *otmp = invent;
  1647.     register int ct = 0;
  1648.  
  1649.     while(otmp){
  1650.         ct++;
  1651.         otmp = otmp->nobj;
  1652.     }
  1653.     return(ct);
  1654. }
  1655.  
  1656. int
  1657. identify(otmp)        /* also called by newmail() */
  1658.     register struct obj *otmp;
  1659. {
  1660.     makeknown(otmp->otyp);
  1661.     otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
  1662.     prinv(NULL, otmp, 0L);
  1663.     return(1);
  1664. }
  1665.  
  1666. #endif /* OVLB */
  1667.  
  1668. /*hack.c*/
  1669.